import {AdapterFactory} from "./frame/apiModel/adapter/AdapterFactory";
import {ModelFactory} from "./frame/apiModel/adapterModel/model5/ModelFactory";
import {DialogController} from "./controller/DialogController";
import {GlobalEnv} from "./utils/GlobalEnv";
import {TimeController} from "./controller/TimeController";
import {Util} from "./utils/Util";
import {DataRouter} from "./frame/dataSource/DataRouter";
import {UnitController} from "./controller/UnitController";
import {ConfigKey} from "./constant/ConfigConstant";
import {ColorStr, RewardType} from "./type/Type";
import {AbilityController} from "./controller/AbilityController";
import {AchievementController} from "./controller/AchievementController";
import {GuiController, OptType} from "./controller/GuiController";
import {TaskController} from "./controller/TaskController";
import {GoodController} from "./controller/GoodController";
import {StoreController} from "./controller/StoreController";
import {gameTypePolicy, LoadRet} from "./policy/GameTypePolicy";
import Configer from "./frame/apiModel/config/Configer";
import {autoCheckTrigger} from "./trigger/AutoCheckTrigger";
import {resumeHeroTrigger} from "./trigger/ResumeHeroTrigger";
import {attackMonsterTrigger} from "./trigger/AttackMonsterTrigger";
import {unitDeadTrigger} from "./trigger/UnitDeadTrigger";
import {
    initAbilityEffectTrigger,
    initBeforeAbilityTrigger,
    initUseAbilityTrigger
} from "./trigger/InitAbilityEffectTrigger";
import {initGoodEffectTrigger} from "./trigger/InitGoodEffectTrigger";
import {initBossAITrigger} from "./trigger/InitBossAITrigger";
import {useItemTrigger} from "./trigger/UseItemTrigger";
import {getItemTrigger} from "./trigger/GetItemTrigger";
import {keyBoradTrigger} from "./trigger/KeyBoradTrigger";
import {transTrigger} from "./trigger/TransTrigger";
import {unitLevelUpTrigger} from "./trigger/UnitLevelUpTrigger";
import {inputTrigger} from "./trigger/InputTrigger";
import {playerExitTrigger} from "./trigger/PlayerExitTrigger";
import {attackedTrigger} from "./trigger/AttackedTrigger";
import {poisonTrigger} from "./trigger/uniqueTrigger/poisonTrigger";
import {
    ControllerOpt,
    DialogControllerOpt,
    GuiControllerOpt,
    GuiId,
    TimeControllerOpt
} from "./controller/model/ControllerOpt";
import {DifficultMode, TimeRewardTriggerType, UnitPoolData} from "./frame/dataSource/DataModel";
import {FinalKey} from "./constant/FinalConstant";
import {buildTrigger} from "./trigger/BuildTrigger";
import {LocalSaveModel} from "./frame/apiModel/adapterModel/model1/LocalSaveModel";
import {Logger} from "./frame/apiModel/config/Logger";
import {PlayerFactory} from "./frame/PlayerFactory";
import {PlayerModel} from "./frame/apiModel/adapterModel/model4/PlayerModel";
import {UnitJson} from "./frame/apiModel/model/StoreJson";
import {CodeUtil} from "./frame/codeAdapter/CodeUtil";
import {GlobalModel} from "./frame/apiModel/adapterModel/model1/GlobalModel";
import {UIConfigKey} from "./constant/UIConfig";
import {forbiddenTrigger} from "./trigger/uniqueTrigger/forbiddenTrigger";
import {selectedTrigger} from "./trigger/SelectedTrigger";
import {PlayerDataKey} from "./frame/dataSource/DataSource";
import {ResourceKey} from "./constant/ResourceConstant";
import MathUtil from "./frame/codeAdapter/MathUtil";
import {hardwareTrigger} from "./trigger/HardwareTrigger";
import {GuiInitAdapter} from "../../initFun/GuiInitFun";
import {SerializeBodyHistory} from "./controller/model/SerializeBody";

export class GameInit {
    constructor() {
        AdapterFactory.getInstance().init();
        ModelFactory.getInstance().init();
    }
    init () {
        Logger.toastSys('游戏开始！');
        PlayerFactory.getInstance().initPlayers();

        // 初始化环境变量
        DataRouter.init();

        this.envInit();
        this.controllerUtilInit();
        this.initTriggerUtil();
    }
    start() {
        GlobalEnv.init();
        this.startInitScript();
        LocalSaveModel.init();
        this.initBaseTrigger();
        // SysToastUtil.toastProduct(`游戏版本: ${Configer.getConfig(ConfigKey.version)}`)
    }
    controllerUtilInit = () => {
        TimeController.getInstance().init();
        DialogController.getInstance().init();


        GuiController.getInstance().init(new GuiInitAdapter());
        GuiController.chooseHeroFun = this.chooseHeroFun;
        GuiController.chooseDiffFun = this.chooseDifficultFun;
        GuiController.chooseArchiveFun = this.chooseArchiveFun;

    }
    controllerInit = () => {
        StoreController.getInstance().init();
        AbilityController.getInstance().init();
        GoodController.getInstance().init();
        AchievementController.getInstance().init();
        UnitController.getInstance().init();
        TaskController.getInstance().init();
    }
    initTriggerUtil = () => {
        // 玩家输入触发
        inputTrigger()
        autoCheckTrigger();
    }

    initBaseTrigger = () => {
        hardwareTrigger();
    }

    initTrigger = () => {
        const path = Configer.getResource(ResourceKey.backSoundPath);
        if (path) {
            const interval = Configer.getUIConfig(UIConfigKey.backSoundInterval);
            TimeController.getInstance().startBackMusic(path, interval);
        }

        // 英雄复活的触发器
        resumeHeroTrigger();
        // 单位死亡后移除附加属性
        // 单位死亡后移除附加属性
        // 胜利与失败判断的触发器
        // 死亡掉落
        unitDeadTrigger();
        initBeforeAbilityTrigger();
        initUseAbilityTrigger();
        initAbilityEffectTrigger();
        initGoodEffectTrigger();
        // bossAi触发
        initBossAITrigger();
        // 使用物品的触发器
        useItemTrigger();
        // 获得物品的触发
        getItemTrigger();
        // // 获得装备的触发
        // getGoodTrigger();
        // 键盘事件的触发器
        keyBoradTrigger();
        // 传送表的触发器
        transTrigger();
        unitLevelUpTrigger()
        // 玩家退出游戏的触发
        playerExitTrigger();
        // 禁止玩家共享单位
        attackedTrigger();
        // 单位建筑完成的触发
        buildTrigger();
        // 毒雾逻辑
        poisonTrigger();
        // 宠物禁止进入
        forbiddenTrigger();
        selectedTrigger();
    }


    envInit = () => {

        const flog = Configer.getConfig(ConfigKey.flog);
        if (!CodeUtil.isNullOrZero(flog)) {
            GlobalModel.fog = false;
            GlobalModel.mask = false;
        }
        GlobalModel.skyModel = "Environment\\Sky\\LordaeronSummerSky\\LordaeronSummerSky.mdl"
        const startInNight = Configer.getConfig(ConfigKey.startInNight) as number;
        if (!CodeUtil.isNullOrZero(startInNight)) {
            const nightStartTime = Configer.getConfig(ConfigKey.nightStartTime) as number;
            GlobalModel.timeOfDay = nightStartTime
        } else {
            const startTime = Configer.getConfig(ConfigKey.dayStartTime) as number;
            GlobalModel.timeOfDay = startTime
        }
        const timeScale = Configer.getConfig(ConfigKey.timeScale) as number;
        GlobalModel.timeOfDayScale = timeScale
        const allyPlayer = PlayerFactory.getInstance().getPlayer(0);
        PlayerFactory.getInstance().mapAllPlayer(
            (player) => {
                // player.setPlayerGoldReward(true)
                if (!allyPlayer.isPlayerAlly(player)) {
                    const allMap = Configer.getFinal(FinalKey.allMapRect);
                    const rect = ModelFactory.getInstance().getRectModel(allMap)
                    player.removeFog(rect);
                }
            }
        )
    }

    startInitScript = () => {
        // 初始化自定义控制器
        this.controllerInit();
        // 选择难度的触发器
        this.chooseDifficult();
        // 2分钟不选择人物自动踢出
        this.timeOutCheck();
    }

    chooseDifficultFun = (difficult: number) => {
        const difficultDatas = DataRouter.getDifficultDatas();
        const currentDiff = GlobalEnv.difficult;
        if (currentDiff && currentDiff >= 0) {
            return;
        }
        GlobalEnv.difficult = difficult;
        // 初始化自定义触发器
        this.initTrigger();
        // 初始化野怪
        this.initGenerateDatas();
        this.loadHero();
        const difficultData = difficultDatas[difficult];
        const mode = difficultData.mode;
        switch (mode) {
            case DifficultMode.pvp: {
                this.initPVP();
                break;
            }
            case DifficultMode.free:{
                break
            }
            default: {
                this.initPVE();
                break;
            }
        }
    }
    chooseDifficult = () => {
        const difficultDatas = DataRouter.getDifficultDatas();
        const len = difficultDatas.length;
        const firstPlayer = PlayerFactory.getInstance().getPlayer(0)
        if (len > 1) {
            Logger.toastProduct('玩家一正在选择难度...')
            const value = firstPlayer.getStoredString(Util.getStoreKey('', 'diff'));
            const useDiffBar = Configer.getConfig(ConfigKey.useDiffBar);
            let currentDiff: number = -1;
            if (!CodeUtil.isNullOrZero(value)) {
                currentDiff = MathUtil.toNumber(value)
            }
            if (!CodeUtil.isNullOrZero(useDiffBar)) {
                PlayerFactory.getInstance().mapAllPlayer(
                    (tempPlayer) => {
                        const opt = new GuiControllerOpt(GuiId.chooseDiffBar, { currentDiff: currentDiff });
                        GuiController.getInstance().showGui(opt, tempPlayer, OptType.open);
                    }
                )
            } else {
                const showDialogCallBack = () => {
                    const arr: DialogControllerOpt[] = [];
                    for (let i = 0; i < difficultDatas.length; i += 1) {
                        const difficult = difficultDatas[i];
                        const id = difficult.id;
                        const front = difficult.front;
                        if (front) {
                            if (front > currentDiff) {
                                continue;
                            }
                        }
                        const index = i;
                        const callBack = (self: ControllerOpt) => {
                            const id = self.id;
                            Logger.toastProduct(id)
                            this.chooseDifficultFun(index);
                        }
                        const opt: DialogControllerOpt = new DialogControllerOpt(id, callBack);
                        arr.push(opt);
                    }
                    DialogController.getInstance().showDialog({ player: firstPlayer, dialogName: '选择难度', optList: arr });
                }
                const timerOpt = new TimeControllerOpt(undefined, showDialogCallBack, 1);
                TimeController.getInstance().startTimer({ time: 0.01, opt: timerOpt });
            }
        } else {
            this.chooseDifficultFun(0);
        }
    }
    timeOutCheck = () => {
        Logger.toastProduct('两分钟未选择人物将视为游戏失败!')
        const callBack = () => {
            PlayerFactory.getInstance().mapAllNotEndPlayingPlayer(
                (player) => {
                    const difficult = GlobalEnv.difficult;
                    if (difficult && difficult >= 0) {
                        const hero = GlobalEnv.getHero(player);
                        if (hero?.isValid()) {
                        } else {
                            TaskController.getInstance().toLose(player);
                        }
                    } else {
                        player.toLose();
                        // CustomDefeatBJ(player, '选择存档超时,游戏失败!');
                    }
                }
            )
        }
        const timerOpt = new TimeControllerOpt(undefined, callBack, 1);
        TimeController.getInstance().startTimer({time: 120, opt: timerOpt});
    }

    continueScript = (player: PlayerModel, serializeBodyHistory: SerializeBodyHistory) => {

        GlobalEnv.bStart = true;

        this.useUnitStore(player, serializeBodyHistory);
        // 初始化商城道具
        this.initArchive(player);
        // 显示多面板
        this.showMultiBorad();
        // 初始化玩家状态
        this.initPlayerState(player);
        // this.initTest(player);
    }
    initPlayerState = (player: PlayerModel) => {
        GlobalEnv.setCheckLose(player, false);

        const hero = GlobalEnv.getHero(player);
        if (hero) {
            player.moveCamera(hero.loc, 0)
        }

        const ach = StoreController.getInstance().getAchStoreHistory(player);
        AchievementController.getInstance().loadApp(player, ach);

        // todo 【需要回退】
        // const path = Configer.getFinal(FinalKey.spellRangeUnitId);
        // const units  = UnitController.getInstance().createUnit(1, { id: path }, player, hero.loc, 0);
        // const unit = units[0];
        // unit.show = false;
        // player.data[PlayerDataKey.targetSpellInfo].effect = unit;
        //
        //
        // const moveTargetEffectPath = Configer.getFinal(FinalKey.moveUnitId);
        // const moveUnits  = UnitController.getInstance().createUnit(1, { id: moveTargetEffectPath }, player, hero.loc, 0);
        // const moveUnit = moveUnits[0];
        // moveUnit.show = false;
        // player.data[PlayerDataKey.moveTargetInfo].effect = moveUnit;



        // 默认打开任务栏
        // const typeTaskRet = TaskController.getInstance().getDoingTask(player);
        // const taskOpt = new GuiControllerOpt(GuiId.taskButton, {});
        // GuiController.getInstance().showGui(taskOpt, player, OptType.open);
        //
        // const damageOpt = new GuiControllerOpt(GuiId.damageButton, {});
        // GuiController.getInstance().showGui(damageOpt, player, OptType.open);

        // const request = { visible: true };
        // const Xopt = new GuiControllerOpt(GuiId.bossLifeBar, request);
        // GuiController.getInstance().showGui(Xopt, player);

        // const path = Configer.getUIConfig(ResourceKeybackSoundPath);
        // GlobalModel.setBackMusic(path)
        // const sound = ModelFactory.getInstance().createSound(path, true, false, false, 0, 0, '')
        // sound.start();
        // const opt1 = new GuiControllerOpt(GuiId.chooseItemBar, { visible: true, itemId: 'si04' });
        // GuiController.getInstance().showGui(opt1, player);

        // GuiController.getInstance().uiEnterFun(player, GuiId.damageBar);
        // GuiController.getInstance().uiEnterFun(player, GuiId.combinationBar);
        // GuiController.getInstance().uiEnterFun(player, GuiId.achievementBar);
    }
    initTest = (player: PlayerModel) => {
        const testDatas = DataRouter.getTestDatas();
        const testData = testDatas && testDatas[0];
        // GlobalEnv.addAdmin(player);
        if (testData) {
            const admins = testData.admin;
            const adminArr = CodeUtil.getArrBySplit(admins);
            const name = player.name;
            const trimName = name?.trim();
            let bAdmin = false;
            let bBlack = false;
            for (let i = 0; i < adminArr.length; i++) {
                const adminStr = adminArr[i];
                if (trimName && trimName === adminStr) {
                    player.data[PlayerDataKey.bWhitelist] = 1;
                    const opt = new GuiControllerOpt(GuiId.adminBar, { });
                    GuiController.getInstance().showGui(opt, player, OptType.open);
                    bAdmin = true;
                }
            }

            let title = '玩家'
            if (bAdmin) {
                title = '作者'
            }

            const blackList = testData.blackList;
            const blackListArr = CodeUtil.getArrBySplit(blackList);
            for (let i = 0; i < blackListArr.length; i++) {
                const blackListStr = blackListArr[i];
                if (trimName && trimName === blackListStr) {
                    player.data[PlayerDataKey.bBlacklist] = 1;
                    bBlack = true;
                }
            }

            if (bBlack) {
                Logger.toastProduct(`${name} 玩家账号已被封禁 如有疑问请加群询问作者!`, undefined, ColorStr.red)
            } else {
                Logger.toastProduct(`欢迎${title} ${name}!`, player)
            }
        }
    }
    // 初始化商城道具
    initArchive = (player: PlayerModel) => {
        const callBack = () => {
            const checkHero = GlobalEnv.getHero(player);
            if (checkHero) {
                const timeRewardDatas = DataRouter.getTimeRewardDatas();
                timeRewardDatas?.forEach((value, index, array) => {
                    const initTime = value.init_time;
                    const intervalTime = value.interval_time;
                    const triggerType = value.triggerType;
                    const checkPlayer = value.checkPlayer;
                    if (triggerType === TimeRewardTriggerType.newSave) {
                        // if (ret === LoadRet.loadAll) {
                        //     return;
                        // }
                    }
                    const repeatCallBack = () => {
                        const isPlaying = player.isNotEndPlaying();
                        if (isPlaying) {
                            const hero = GlobalEnv.getHero(player);
                            const conditionIds = value.condition;
                            const conditionArr = CodeUtil.getArrBySplit(conditionIds);
                            const ret = TaskController.getInstance().checkConditions(hero, conditionArr, undefined, player);
                            const bCheck = ret.success;
                            if (bCheck) {
                                const rewards = value.reward;
                                const rewardArr = CodeUtil.getArrBySplit(rewards);
                                for (let i = 0; i < rewardArr.length; i++) {
                                    const tempReward = rewardArr[i];
                                    if (!CodeUtil.isNullOrZero(checkPlayer)) {
                                        const playerId = player.playerId;
                                        const isCheck = (playerId === i);
                                        if (isCheck) {
                                        } else {
                                            continue;
                                        }
                                    }
                                    TaskController.getInstance().reward(hero, hero, RewardType.bag, tempReward);
                                }
                            }
                            if (!CodeUtil.isNullOrZero(intervalTime)) {
                                const timerOpt = new TimeControllerOpt(undefined, repeatCallBack, 1);
                                TimeController.getInstance().startTimer({ time: intervalTime, opt: timerOpt });
                            }
                        }
                    }
                    const timerOpt = new TimeControllerOpt(undefined, repeatCallBack, 1);
                    TimeController.getInstance().startTimer({ time: initTime, opt: timerOpt });
                })
            } else {
                const timerOpt = new TimeControllerOpt(undefined, callBack, 1);
                TimeController.getInstance().startTimer({ time: 1, opt: timerOpt });
            }
        }
        const timerOpt = new TimeControllerOpt(undefined, callBack, 1);
        TimeController.getInstance().startTimer({ time: 1, opt: timerOpt });
    }
    loadHero = () => {
        PlayerFactory.getInstance().mapAllNotEndPlayingPlayer(
            (player) => {
                this.initTest(player)
                StoreController.getInstance().getStore(player, gameTypePolicy.getSaveControllerNos());
                gameTypePolicy.chooseLoad(player, this.chooseArchiveFun);
            }
        )
    }

    chooseArchiveFun = (player: PlayerModel) => {
        const saveControllerNos = gameTypePolicy.getSaveControllerNos();
        const serializeBodyHistory = player.data[PlayerDataKey.storeCurrent];
        const ret = gameTypePolicy.loadRet;
        switch (ret) {
            // 全新的开始
            case LoadRet.newStart:{
                const serializeBodyHistory = StoreController.getInstance().getStore(player, saveControllerNos, true);
                this.randomUnit(player, this.chooseHeroFun, serializeBodyHistory);
                break;
            }
            // 只是重新选择英雄
            case LoadRet.newUnit: {
                this.usePlayerStore(player, serializeBodyHistory);
                this.randomUnit(player, this.chooseHeroFun, serializeBodyHistory);
                break;
            }
            // 加载全部
            case LoadRet.loadAll: {
                this.usePlayerStore(player, serializeBodyHistory);
                const hero = GlobalEnv.getHero(player);
                if (hero) {
                    this.continueScript(player, serializeBodyHistory);
                } else {
                    this.randomUnit(player, this.chooseHeroFun, serializeBodyHistory);
                }
                break;
            }
        }
    }

    usePlayerStore = (player: PlayerModel, serializeBodyHistory: SerializeBodyHistory) => {
        const controllerNos = gameTypePolicy.getLoadControllerNos1(player);
        const len = controllerNos.length;
        if (len > 0) {
            for (let i = 0; i < len; i++) {
                const no = controllerNos[i];
                StoreController.getInstance().useStoreByControllerNo(serializeBodyHistory, player, no);
            }
            return serializeBodyHistory;
        }
    }
    useUnitStore = (player: PlayerModel, serializeBodyHistory: SerializeBodyHistory) => {
        const controllerNos = gameTypePolicy.getLoadControllerNos2(player);
        const len = controllerNos.length;
        if (len > 0) {
            for (let i = 0; i < len; i++) {
                const no = controllerNos[i];
                StoreController.getInstance().useStoreByControllerNo(serializeBodyHistory, player, no);
            }
            return serializeBodyHistory;
        }
    }
    chooseHeroFun = (player: PlayerModel, id: string) =>  {
        const hero = GlobalEnv.getHero(player);
        const startPos = player.startLocation;

        if (hero) {
        } else {
            const unitJson: UnitJson = { id: id, e: 0 };
            UnitController.getInstance().createUnit(1, unitJson, player, startPos, 0, true);
        }
        const useBox: number = Configer.getConfig(ConfigKey.useBox)
        if (!CodeUtil.isNullOrZero(useBox)) {
            const box = GlobalEnv.getBox(player);
            if (box) {
            } else {
                const boxId = Configer.getFinal(FinalKey.boxId)
                UnitController.getInstance().createBox(boxId, player, startPos, startPos);
            }
        }
        const serializeBodyHistory = player.data[PlayerDataKey.storeCurrent];
        this.continueScript(player, serializeBodyHistory);
    }
    randomUnit = (player: PlayerModel, chooseHeroFun: (player: PlayerModel, id: string, serializeBodyHistory: SerializeBodyHistory) => void, serializeBodyHistory: SerializeBodyHistory) => {
        player.allFood = 1;
        const difficult = StoreController.getInstance().getMaxDifficult(player)
        const achs = AchievementController.getInstance().getAchievement(player);
        const unitArr: UnitPoolData[] = UnitController.getInstance().getInitUnitArrs(player, difficult, achs);
        const randomNum = Configer.getConfig(ConfigKey.initheroAmount) as number;
        if (randomNum === 0) {
        } else if (randomNum === 1) {
            let index = player.getRandomInt(0, unitArr.length - 1);
            const unitPoolDate = unitArr[index];
            chooseHeroFun(player, unitPoolDate.id, serializeBodyHistory);
        } else {
            const request = { unitPoolDatas: unitArr };
            const opt = new GuiControllerOpt(GuiId.chooseHeroBar, request);
            GuiController.getInstance().showGui(opt, player, OptType.open);
        }
    }
    initGenerateDatas = () => {
        UnitController.getInstance().initAffixByDiff();
        const generateDatas = DataRouter.getGenerateDatas();
        for (let i = 0; i < generateDatas.length; i++) {
            const generateData = generateDatas[i];
            const id = generateData.id;
            const localPlayer = PlayerFactory.getInstance().getLocalPlayer();
            const random = localPlayer.getRandomInt(0, 100);
            const appearProbability = generateData.appear_probability;
            if (appearProbability) {
                if (appearProbability >= random) {
                    const delayTime = generateData.init_time;
                    const num = generateData.num;
                    if (!CodeUtil.isNullOrZero(delayTime)) {
                        UnitController.getInstance().initGenerate(generateData, delayTime, num);
                    }
                }
            } else {
                Logger.toastError(`生成表: ${id}, 生成概率不能为空！`);
            }
        }
    }
    showMultiBorad = () => {
        const callBack = () => {
            // const borad = GlobalEnv.multiboard;
            // MultiboardSetTitleText(borad, '难度一');
            // const columns: { text: string, key: string }[] = MultiBoradBar.columns;
            // MultiboardSetColumnCount(borad, columns.length);
            // const playerNum = PlayerFactory.getInstance().getPlayingPlayerNum() + 1;
            // MultiboardSetRowCount(borad, playerNum);
            // MultiboardSetItemsWidth(borad,  0.3 / columns.length);
            // MultiboardSetItemsStyle(borad,  true, false);
            // MultiBoradBar.reflushMultiBorad(borad);
            // MultiboardSuppressDisplay(false);
            // MultiboardDisplayBJ(true, borad);
        }
        const timerOpt = new TimeControllerOpt(undefined, callBack, 1);
        TimeController.getInstance().startTimer({time: 1, opt: timerOpt});
    }
    initPVP() {
        PlayerFactory.getInstance().mapAllNotEndPlayingPlayer(
            (player1) => {
                PlayerFactory.getInstance().mapAllNotEndPlayingPlayer(
                    (player2) => {
                        if (player2 === player1) {
                        } else {
                            player1.setAlly(player2, false)
                        }
                    }
                )
            }
        )
    }
    initPVE() {
        // *防守图出兵逻辑
        attackMonsterTrigger();
    }

}